#!/bin/bash
# 依赖工具：ethtool, tcpdump, mii-tool, wget, timeout
trap kill_self SIGINT SIGTERM SIGQUIT

flat_ovs="br-ex"
gateway="192.168.100.1"
dns="202.112.144.236 8.8.8.8"
control_dst="192.168.100.254"
compute_dst="10.8.8.254"
storage_dst="10.6.6.254"
compute_ovs="com-balancing"
storage_ovs="sto-balancing"
tempory_net="10.6.6.253/24"
remote_servers=(10.6.6.2 10.8.8.2)
file="eth-initd.start"
netconfigfile="/etc/network/interfaces"


function kill_self(){
    program=$0
    name=${program##*/}
    echo "killing $name"
    for p in `ps axu | grep $name| grep -v color| grep -v grep`
    do
        sudo kill -9 $p
    done
}

# 配置$compute_ovs与$storage_ovs临时流表，
# 保证ovs连接不上控制器时，均衡交换机退化为单链路通信
function configure_ovs(){
    ovses=($compute_ovs $storage_ovs)
    for s in ${ovses[*]}
    do
        sudo ovs-vsctl list-br| grep $s >/dev/null 2>&1    
        if [[ $? -eq 0 ]];then
            echo "Configure $s..."
            sudo ifconfig $s up
            sudo ovs-ofctl del-flows $s
            ovs_eths=(`sudo ovs-vsctl list-ports $s`)
            for eth in ${ovs_eths[@]}
            do
                sudo ifconfig $eth 0.0.0.0
                sudo ovs-ofctl add-flow $s "priority=0 idle_timeout=0, in_port=$eth, action=output:local" 
            done
            sudo ovs-ofctl add-flow $s "priority=0 idle_timeout=0, in_port=local, action=output:${ovs_eths[0]}" 
        fi
    done
}

#param1: openvswitch name
#param2: port name
function del_br_port() {
    s=$1
    port=$2
    sudo ovs-vsctl list-br| grep $s >/dev/null 2>&1    
    if [[ $? -eq 0 ]];then
        sudo ovs-vsctl list-ports $s | grep $port
        if [[ $? -eq 0 ]];then
            echo "Unbinding $port from $s"
            sudo ovs-vsctl del-port $s $port
            return 0
        fi
    fi
    return 1
}


function is_phy_eth(){
    sudo mii-tool "$1"  >/dev/null 2>&1
    if [[ $? -eq 0 ]];then 
        return 0
    fi
    return 1
}

configure_ovs

# 配置网络
isempty=`cat $netconfigfile| grep eth-init|grep -v grep|grep -v color`
if [[  "$isempty" != "" ]];then
    echo "The network config($netconfigfile) was generated by $0, so excited."
    echo -e "  if regenerated by $0, please clean up $netconfigfile"
    exit 0
fi

# 查找所有物理端口
eths_t=(`ifconfig -a |grep "Link encap:Ethernet" | awk -F" " '{print $1}'`)
eths=()
i=0
for eth in ${eths_t[*]}
do
    is_phy_eth $eth
    if [[ $? -eq 0 ]];then
        eths[$i]=$eth
        i=$((i+1))
        sudo ifconfig $eth up
        echo "Set $eth up "
    fi
done

echo "Obtaining the host information from the server (${remote_servers[*]})..."
#Look up a storage network interface, use it as tempory networ
del_br_port_flag="false"
for eth in ${eths[*]}
do
    sudo timeout 3 tcpdump -nn -i $eth -c 1 dst $storage_dst >/dev/null 2>&1
    if [[ $? -eq 0 ]];then
        del_br_port $storage_ovs $eth
        if [[ $? -eq 0 ]];then
            del_br_port_flag="true"
        fi
        storage_ip_t=$(sudo ifconfig $storage_ovs| grep "inet addr:"|\
                      grep -v grep| grep -v color|\
                      awk -F":" '{print $2}'|awk -F" " '{print $1}')
        if [[ $? -ne 0 ]];then
            storage_ip_t=""
        fi
        sudo ifconfig $storage_ovs 0.0.0.0
        sudo ifconfig $eth $tempory_net
        echo "ifconfig $eth $tempory_net"
        tempory_eth=$eth
        break
    fi
done

# 获得host 序列号
flag=""
for remote_server in ${remote_servers[@]}
do
    timeout 3 wget -q -nv $remote_server"/"$file  2>/dev/null
    if [[ -f $file ]];then
        flag=`cat $file`
        rm -f $file
        echo "$flag"|[ -n "`sed -n '/^[0-9][0-9]*$/p'`" ]
        if [[ $? -eq 0 ]];then
            dst=$remote_server
            hostnum=$flag
            # clean up tempory eth
            sudo ifconfig $tempory_eth 0.0.0.0
            if [[ "$del_br_port_flag" == "true" ]];then
                sudo ifconfig $storage_ovs $storage_ip_t"/24"
                sudo ovs-vsctl add-port $storage_ovs $tempory_eth
                echo "Restore:Binding $tempory_eth into $storage_ovs, and reconfigure ovs."
                configure_ovs
            fi
            break
        fi
   fi
done

# 若获得不了主机序列号，则退出
echo "$flag"|[ -n "`sed -n '/^[0-9][0-9]*$/p'`" ]
if [[ $? -ne 0 ]];then
    echo "Remote server ${remote_servers[*]} is not running,so exited."
    exit 0
fi


echo "Procesing..."

# 提取存储网段IP
#ip=`ifconfig | grep $(echo "$dst"|awk -F"." '{print$1"."$2"."$3"."}')|\
#            awk -F":" '{print $2}'|awk -F" " '{print $1}'`
#seq=`echo $ip|awk -F"." '{print $4}'`
seq=$((hostnum+4))
storage_ip=`echo $storage_dst|awk -F"." '{print $1"."$2"."$3"."}'`"$seq"
control_ip=`echo $control_dst|awk -F"." '{print $1"."$2"."$3"."}'`"$seq"
compute_ip=`echo $compute_dst|awk -F"." '{print $1"."$2"."$3"."}'`"$seq"

#设置主机名
if [[ $seq -gt 4 ]];then
    hostname="compute$((seq-4))"
elif [[ $seq -eq 2 ]];then
    hostname="storage"
elif [[ $seq -eq 3 ]];then
    hostname="network"
elif [[ $seq -eq 4 ]];then
   hostname="controller"
fi
hostnamectl status| grep hostname| grep $hostname >/dev/null
if [[ $? -ne 0 ]];then
    echo "set hostname=$hostname"
    sudo hostnamectl set-hostname $hostname --static
fi


#物理拓扑情况：交换机A单端口为100Mb/s，交换机B1/B2单端口为1000Mb/s,控制网络连接交换机A 
#              计算网络连接交换机B1, 存储网络连接交换机B2 
#              同时,因为计算网络需要支持OpenStack的Flat网络，所以交换机A与交换机B1相连。
#根据物理拓扑情况，确定控制网口与用于浮动IP的网口
eth100=""
# 寻找100Mb网口，作为控制口
echo "Find 100Mb eth in ${eths[*]}"
for eth in ${eths[*]}
do
    res=`sudo ethtool $eth | grep "Speed: 100Mb/s" | grep -v grep | grep -v color`
    if [[ "$res" != "" ]];then
	    sudo timeout 3 tcpdump -nn -i $eth -c 1 dst $control_dst >/dev/null 2>&1
	    if [[ $? -eq 0 ]];then
            eth100=$eth
            eths=(${eths[@]/$eth100})
            break
	    fi
    fi
done

# 若无100Mb网口，寻找1000Mb/s网口作为控制口
if [[ "$eth100" == "" ]];then
    echo "Find 1000Mb eth in ${eths[*]}"
    for eth in ${eths[*]}
    do
        res=`sudo ethtool $eth | grep "Speed: 1000Mb/s"|grep -v grep | grep -v color`
        if [[ "$res" != "" ]];then
    	    sudo timeout 3 tcpdump -nn -i $eth -c 1 dst $control_dst >/dev/null 2>&1
    	    if [[ $? -eq 0 ]];then
                eth100=$eth
                eths=(${eths[@]/$eth100})
                break
    	    fi
        fi
    done
fi


if [[ "$eth100" == "" ]];then
    echo "Can not find control network interface in ${eths[@]}, so exited."
    exit 2
fi
echo "The controller network interface is $eth100"
del_br_port $storage_ovs $eth100
del_br_port $compute_ovs $eth100
sudo ifconfig $eth100 $control_ip"/16"
sudo route -n | awk -F" " '{print $2}'| grep "$gateway"|grep -v grep | grep -v color >/dev/null
if [[ $? -ne 0 ]];then
    sudo route add default gw $gateway
fi 
sudo echo "nameserver 202.112.144.236" >/etc/resolv.conf
netconfig="#Generated by eth-init,which is writed Haifeng Li (haifengli@bjtu.edu.cn).
auto $eth100
iface $eth100 inet static
address $control_ip
netmask 255.255.0.0
gateway $gateway
dns-nameservers $dns\n\n"

# 检查$flat_ovs是否有连接外网的端口
eth_flat=""
flag=`sudo ovs-vsctl list-br|grep $flat_ovs|grep -v grep | grep -v color`
if [[ "$flag" == "" ]];then
    sudo ovs-vsctl add-br $flat_ovs
fi
eth_flats=(`sudo ovs-vsctl list-ports $flat_ovs|grep -v $flat_ovs| grep -v grep | grep -v color`)
for i in ${eth_flats[*]}
do
    is_phy_eth $i
    if [[ $? -eq 0 ]];then
        if [[ "$eth_flat" != "" ]];then
            del_br_port $flat_ovs $i
        fi
	    sudo timeout 3 tcpdump -nn -i $i -c 1 dst $control_dst >/dev/null 2>&1
	    if [[ $? -eq 0 ]];then
            eth_flat=$i
            eths=(${eths[@]/$eth_flat})
        fi
    fi
done

if [[ "$eth_flat" == "" ]];then
    # 查找Flat网络口
    for eth in ${eths[*]}
    do
        res=`sudo ethtool $eth | grep "Speed: 1000Mb/s"|grep -v grep | grep -v color`
        if [[ "$res" != "" ]];then
    	    sudo timeout 3 tcpdump -nn -i $eth -c 1 dst $control_dst >/dev/null 2>&1
    	    if [[ $? -eq 0 ]];then
                eth_flat=$eth
                eths=(${eths[@]/$eth_flat})
                break
    	    fi
        fi
    done
    if [[ "$eth_flat" == "" ]];then
        echo "Can not find flat network interface, so exited."
        exit 1
    fi
    sudo ovs-vsctl add-port $flat_ovs $eth_flat
fi


del_br_port $storage_ovs $eth_flat
del_br_port $compute_ovs $eth_flat
# 添加Flat网口名称信息到netconfig,便于管理员配置nova
netconfig="$netconfig""
# Flat network interface is $eth_flat.\n\n
"
echo "The Flat network interface is $eth_flat"

# 查找计算网络
echo "Looking up compute interfaces..."
compute_eths=()
i=0
for eth in ${eths[*]}
do
    sudo timeout 3 tcpdump -nn -i $eth -c 1 dst $compute_dst >/dev/null 2>&1
    if [[ $? -eq 0 ]];then
        compute_eths[$i]=$eth
        i=$((i+1))
        eths=(${eths[@]/$eth})
    fi
done

for eth in ${compute_eths[*]}
do
    sudo ifconfig $eth 0.0.0.0
done
echo -e "\tCompute network interfaces are ${compute_eths[*]}"

## 创建compute_ovs,配置IP
flag=`sudo ovs-vsctl list-br|grep $compute_ovs|grep -v grep | grep -v color`
if [[ "$flag" == "" ]];then
    sudo ovs-vsctl add-br $compute_ovs
fi

sudo ifconfig $compute_ovs $compute_ip"/24"
netconfig="$netconfig""
auto $compute_ovs
iface $compute_ovs inet static
address $compute_ip
netmask 255.255.255.0
\n\n
"

compute_eths_t=(${compute_eths[@]})
## 添加端口到compute_ovs
for eth in `sudo ovs-vsctl list-ports $compute_ovs`
do
    sudo ovs-vsctl del-port $compute_ovs $eth
done
for eth in ${compute_eths[*]}
do
    sudo ovs-vsctl add-port $compute_ovs $eth
done

## 配置临时流表，使计算网络的负载均衡ovs在没有连接控制器时，仍然能够工作
sudo ovs-ofctl del-flows $compute_ovs
for eth in ${compute_eths_t[@]}
do
    sudo ovs-ofctl add-flow $compute_ovs "priority=0 idle_timeout=0, in_port=$eth, action=output:local"
done
sudo ovs-ofctl add-flow $compute_ovs "priority=0 idle_timeout=0, in_port=local, action=output:${compute_eths_t[0]}"

# 查找存储网络
echo "Looking up storage network interfaces..."
storage_eths=()
i=0
for eth in ${eths[*]}
do
    sudo timeout 3 tcpdump -nn -i $eth -c 1 dst $storage_dst >/dev/null 2>&1
    if [[ $? -eq 0 ]];then
        storage_eths[$i]=$eth
        i=$((i+1))
        eths=(${eths[@]/$eth})
    fi
done

for eth in ${storage_eths[*]}
do
    sudo ifconfig $eth 0.0.0.0
done
echo -e "\tStorage network interfaces are ${storage_eths[*]}"

## 创建storage_ovs,配置IP
flag=`sudo ovs-vsctl list-br|grep $storage_ovs|grep -v grep | grep -v color`
if [[ "$flag" == "" ]];then
    sudo ovs-vsctl add-br $storage_ovs
fi



sudo ifconfig $storage_ovs $storage_ip"/24"
netconfig="$netconfig""
auto $storage_ovs
iface $storage_ovs inet static
address $storage_ip
netmask 255.255.255.0
\n\n
"
storage_eths_t=(${storage_eths[@]})

## 添加端口到storage_ovs
### 删除old端口
for eth in `sudo ovs-vsctl list-ports $storage_ovs`
do
    sudo ovs-vsctl del-port $storage_ovs $eth
done
for eth in ${storage_eths[*]}
do
    sudo ovs-vsctl add-port $storage_ovs $eth
done

## 配置临时流表，使存储网络的负载均衡ovs在没有连接控制器时，仍然能够工作
sudo ovs-ofctl del-flows $storage_ovs
for eth in ${storage_eths_t[@]}
do
    sudo ovs-ofctl add-flow $storage_ovs "priority=0 idle_timeout=0, in_port=$eth, action=output:local"
done
sudo ovs-ofctl add-flow $storage_ovs "priority=0 idle_timeout=0, in_port=local, action=output:${storage_eths_t[0]}"

sudo echo -e "$netconfig" > $netconfigfile
sudo grep -Horl --exclude=hosts "my_ip = 192" /etc/ | xargs sed "s/my_ip = 1.*/my_ip = $control_ip/g" -i >/dev/null 2>&1
sudo grep -Horl --exclude=hosts "my_ip = 10" /etc/ | xargs sed "s/my_ip = 10.*/my_ip = $compute_ip/g" -i >/dev/null 2>&1
sudo grep -Horl --exclude=hosts "local_ip = 10" /etc/ | xargs sed "s/local_ip = 10.*/local_ip = $compute_ip/g" -i >/dev/null 2>&1

host_uuid=`uuidgen`
sed -i "s/host_uuid = .*/host_uuid = \"$host_uuid\"/g" /etc/libvirt/libvirtd.conf
sudo sed -i "s/\"pool_password\" \: .*/\"pool_password\" : \"$hostname:melonli@qq.com\",/g" /home/melonli/exp/bin/config.txt
sudo sed -i "s/\"pool_password\" \: .*,/\"pool_password\" : \"$hostname:melonli@qq.com\",/g" /home/melonli/exp/bin2/pools.txt
hostname|xargs echo > /etc/salt/minion_id
sed -i "s/Hostname=.*/Hostname=$hostname/g" /etc/zabbix/zabbix_agentd.conf
exit 0
